package com.tom.architect.party5.day38.simple7.proxy;

import com.tom.architect.party5.day38.simple7.base.BasePresenter;
import com.tom.architect.party5.day38.simple7.base.BaseView;
import com.tom.architect.party5.day38.simple7.inject.InjectPresenter;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

// IMvpProxy 的实现类, 传入View
public class MvpProxyImpl<V extends BaseView> implements IMvpProxy {
    // mView是继承自BaseView的 Activity、Fragment、ViewGroup...
    private V mView; // 静态代理：被代理的对象
    private List<BasePresenter> mPresenters; // 存起来，用于detach

    // 构造函数，IMvpProxy的实现类 传入view
    public MvpProxyImpl(V view) {
        // TODO 做一下view 空null 判断，判断view是否是个接口。传入被代理的静态对象
        this.mView = view;
        this.mPresenters = new ArrayList<>();
    }

    @Override
    public void bindAndCreatePresenter() {
        // 自己实现：IOC 注入Presenter。通过反射/Dagger，实现注入。
        Field[] fields = mView.getClass().getDeclaredFields();
        for (Field field : fields) {
            InjectPresenter injectPresenter = field.getAnnotation(InjectPresenter.class);
            if (injectPresenter != null) {
                // 创建注入
                Class<? extends BasePresenter> presenterClazz = null;
//                try {
//                    // TODO 添加判断类型，instanceOf？ 获取它的父类，如果不是继承自BasePresenter，就抛异常。
//                    // TextView 添加注入后，这里不会进入异常代码？
//                    presenterClazz = (Class<? extends BasePresenter>) field.getType();
//                } catch (Exception e) {
//                    // 其他的注入
//                    throw new RuntimeException("No Support inject Presenter type: " + field.getType().getName());
//                }
                presenterClazz = (Class) field.getType(); // 泛型擦除
                // 1.泛型的擦除,避免TextView 也添加了注入@InjectPresenter。提示用户1
                if (!BasePresenter.class.isAssignableFrom(presenterClazz)) {
                    //这个class是否继承自 BasePresenter,如果不是抛异常
                    throw new RuntimeException("No Support inject present type: " + presenterClazz.getName());
                }
                BasePresenter basePresenter = null;
                try {
                    basePresenter = presenterClazz.newInstance(); // 反射创建Presenter
                    basePresenter.attach(mView); // 去哪里解绑？绑定逻辑。
                    field.setAccessible(true);
                    // 设置子类中，mPresenter的值
                    field.set(mView, basePresenter);
                    mPresenters.add(basePresenter);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                // 检测view层，是否实现了 Presenter的View接口，如果没有就抛异常
                checkView(basePresenter);
            }
        }
    }

    // 有注入，必须要实现相关的接口。
    // 2.动态检测view层的接口，是否实现了 Presenter的View接口，如果没有就抛异常
    private void checkView(BasePresenter basePresenter) {
        //2.1 拿到Presenter的所有接口
        Type genType = basePresenter.getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        Class viewClazz = ((Class) params[0]);

        //2.2 拿到view层的所有接口
        Class[] viewClasses = mView.getClass().getInterfaces();
        //2.3 View层没有实现，就抛异常。
        boolean isImplementsView = false;
        for (Class viewClass : viewClasses) {
            if (viewClass.isAssignableFrom(viewClazz)) {
                isImplementsView = true;
            }
        }
        if (!isImplementsView) { // 没有实现
            // Activity 必须实现View的接口，提示用户2.
            throw new RuntimeException("注入的时候" + mView.getClass().getSimpleName() +
                    " View must implements " + viewClazz.getName());
        }
    }

    // 解绑Presenter
    @Override
    public void unbindPresenter() {
        // 解绑所有Presenter
        for (BasePresenter presenter : mPresenters) {
            presenter.detach(); // 解绑 IOC创建的P。
        }
        mView = null;
    }

}
